﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using SqlSugar;

namespace 数据迁移工具.Common
{
    /// <summary>
    /// 在程序运行时动态地创建类并编译
    /// </summary>
    public class DynamicHelper
    {
        private static List<MetadataReference> references;
        public static Assembly ModelAssembly { get; set; }

        /// <summary>
        /// 动态构建程序集
        /// </summary>
        public static void AssemblyBuild(string modelPath,string assemblyName = "Default.Models")
        {
            // 创建语法树
            List<SyntaxTree> syntaxTrees = new List<SyntaxTree>();

            foreach (var file in Directory.GetFiles(modelPath))
            {
                string code = File.ReadAllText(file);
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
                syntaxTrees.Add(syntaxTree);
            }

            if(references == null)
            {
                // 引用必要的程序集
                /*  
                    获取当前应用程序域中已加载的所有程序集。
                    过滤掉动态生成的程序集（因为它们没有物理文件路径）。
                    将每个程序集的物理文件路径转换为 MetadataReference 对象。
                    将结果存储在一个 List<MetadataReference> 中，供 Roslyn 编译器使用。
                 */
                references = AppDomain.CurrentDomain.GetAssemblies()
                    .Where(a => !a.IsDynamic)
                    .Select(a => MetadataReference.CreateFromFile(a.Location))
                    .Cast<MetadataReference>()
                    .ToList();

                // 添加额外的程序集引用(默认情况下只加载 System.Runtime 下的程序集
                var dataAnnotationsAssembly = typeof(RequiredAttribute).Assembly; // System.ComponentModel.DataAnnotations
                references.Add(MetadataReference.CreateFromFile(dataAnnotationsAssembly.Location));

                var sqlSugarAssembly = typeof(SqlSugarClient).Assembly; // SqlSugar
                references.Add(MetadataReference.CreateFromFile(sqlSugarAssembly.Location));
            }
          
            // 创建编译选项
            CSharpCompilationOptions options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);

            // 创建编译
            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                syntaxTrees.ToArray(),
                references,
                options);

            // 编译代码
            using (var ms = new MemoryStream())
            {
                var result = compilation.Emit(ms);

                if (!result.Success)
                {
                    foreach (var diagnostic in result.Diagnostics)
                    {
                        ConsoleLog.Error("RichText","dynamic: " + diagnostic.ToString());
                    }
                    return;
                }

                // 加载编译后的程序集
                ms.Seek(0, SeekOrigin.Begin);
                ModelAssembly = Assembly.Load(ms.ToArray());
            }
        }

        /// <summary>
        /// 动态调用测试
        /// </summary>
        public static void DynamicCallMethod()
        {
            Type? type = ModelAssembly.GetType("DM2MySQL.Models.Data_District");
            object? instance = Activator.CreateInstance(type);
            MethodInfo? method = type.GetMethod("ShowCode");
            object? val = method.Invoke(instance, null);
            Debug.WriteLine(val);

            Type? type2 = ModelAssembly.GetType("DM2MySQL.Models.Data_Community");
            object? instance2 = Activator.CreateInstance(type2);
            MethodInfo? method2 = type2.GetMethod("ShowComID");
            object? val2 = method2.Invoke(instance2, null);
            Debug.WriteLine(val2);
        }
    }
}
